<?php

/**
 * @desc Base class filter-components collaborating in user request process
 *
 */
abstract class Kernel_Filter extends Kernel_Component implements Kernel_Filter_Interface 
{

    /**
     * Start filter.
     *
     */
    public function process() 
    {
        if (!$this->_allowed()) {
            $this->_deny('Not allowed');
        }
    }

    /**
     * @desc Return whether current filter processing is allowed. E.g. for the 
     * current user.
     *
     * @return  boolean
     */
    protected function _allowed() 
    {
        return true;
    }

    /**
     * @desc Delegate processing to the specified filter.
     *
     * @param   Kernel_Filter_Interface $filter
     * @return  Kernel_Filter
     */
    protected function _forward(Kernel_Filter_Interface $filter) 
    {
        $filter->process();
        return $this;
    }

    /**
     * @desc NOT FOUND.
     * Abort request processing and generate 404 ERROR.
     *
     * @param   string  $message
     * @throws  Kernel_Filter_Exception_NotFound
     */
    protected function _abort($message) 
    {
        throw new Kernel_Filter_Exception_NotFound($this->_specialize($message));
    }

    /**
     * @desc FORBIDDEN.
     * Abort request processing and generate 403 ERROR.
     *
     * @param   string  $message
     * @param   boolean $force
     * @throws  Kernel_Filter_Exception
     */
    protected function _deny($message, $force = false) 
    {
        if (!$force && !Security_Session::isAuthorized()
            // :KLUDGE: morozov 13022008: уродско, но работает как надо.
            && Kernel_Mode_Factory::get() instanceof Kernel_Mode_Html) {
            $this->_location(
                (Application::getRequest()->isMultilang() ? __lang() . '/' : '') .
                'user/login/?back=' . urlencode(Application::getRequest()->requestUri())
                );
        } else {
            throw new Kernel_Filter_Exception_Forbidden($this->_specialize($message));
        }
    }

    /**
     * @desc Abort request processing and relocate agent by the specified URL.
     *
     * @param   string  $url
     * @param   boolean $permanent
     */
    protected function _location($url, $permanent = false) 
    {
        throw $permanent
            ? new Kernel_Filter_Exception_Location_MovedPermanently($url)
            : new Kernel_Filter_Exception_Location_Found($url);
    }

    /**
     * @desc Add prefix to the message to specify filter name which throws 
     * exception. 
     *
     * @param   string  $message
     * @return  string
     */
    private function _specialize($message) 
    {
        return get_class($this) . ': ' . $message;
    }
    
}
